<template>
  <div
    class="richTextToolbar"
    ref="richTextToolbar"
    :style="style"
    :class="{ isDark }"
    @click.stop.passive
    v-if="showRichTextToolbar"
  >
    <el-tooltip  :content="t('richTextToolbar.bold')" placement="top">
      <div class="btn" :class="{ active: formatInfo.bold }" @click="toggleBold">
        <span class="icon iconfont iconzitijiacu"></span>
      </div>
    </el-tooltip>

    <el-tooltip :content="t('richTextToolbar.italic')" placement="top">
      <div
        class="btn"
        :class="{ active: formatInfo.italic }"
        @click="toggleItalic"
      >
        <span class="icon iconfont iconzitixieti"></span>
      </div>
    </el-tooltip>

    <el-tooltip :content="t('richTextToolbar.underline')" placement="top">
      <div
        class="btn"
        :class="{ active: formatInfo.underline }"
        @click="toggleUnderline"
      >
        <span class="icon iconfont iconzitixiahuaxian"></span>
      </div>
    </el-tooltip>

    <el-tooltip :content="t('richTextToolbar.strike')" placement="top">
      <div
        class="btn"
        :class="{ active: formatInfo.strike }"
        @click="toggleStrike"
      >
        <span class="icon iconfont iconshanchuxian"></span>
      </div>
    </el-tooltip>

    <el-tooltip :content="t('richTextToolbar.fontFamily')" placement="top">
      <el-popover placement="bottom" trigger="hover">
        <template #default>
          <div class="fontOptionsList" :class="{ isDark }">
            <div
              class="fontOptionItem"
              v-for="item in fontFamilyListComputed"
              :key="item.value"
              :style="{ fontFamily: item.value }"
              :class="{ active: formatInfo.font === item.value }"
              @click="changeFontFamily(item.value)"
            >
              {{ item.name }}
            </div>
          </div>
        </template>
        <template #reference>
          <div class="btn">
            <span class="icon iconfont iconxingzhuang-wenzi"></span>
          </div>
        </template>
      </el-popover>
    </el-tooltip>

    <el-tooltip :content="t('richTextToolbar.fontSize')" placement="top">
      <el-popover placement="bottom" trigger="hover">
        <template #default>
          <div class="fontOptionsList" :class="{ isDark }">
            <div
              class="fontOptionItem"
              v-for="item in fontSizeList"
              :key="item"
              :style="{
                fontSize: item + 'px',
                height: (item < 30 ? 30 : item + 10) + 'px'
              }"
              :class="{ active: formatInfo.size === item + 'px' }"
              @click="changeFontSize(item)"
            >
              {{ item }}px
            </div>
          </div>
        </template>
        <template #reference>
          <div class="btn">
            <span class="icon iconfont iconcase fontColor"></span>
          </div>
        </template>
      </el-popover>
    </el-tooltip>

    <el-tooltip :content="t('richTextToolbar.color')" placement="top">
      <el-popover placement="bottom" trigger="hover">
        <template #default>
          <Color :color="fontColor" @change="changeFontColor"></Color>
        </template>
        <template #reference>
          <div class="btn" :style="{ color: formatInfo.color }">
            <span class="icon iconfont iconzitiyanse"></span>
          </div>
        </template>
      </el-popover>
    </el-tooltip>

    <el-tooltip
      :content="t('richTextToolbar.backgroundColor')"
      placement="top"
    >
      <el-popover placement="bottom" trigger="hover">
        <template #default>
          <Color
            :color="fontBackgroundColor"
            @change="changeFontBackgroundColor"
          ></Color>
        </template>
        <template #reference>
          <div class="btn">
            <span class="icon iconfont iconbeijingyanse"></span>
          </div>
        </template>
      </el-popover>
    </el-tooltip>

    <el-tooltip :content="t('richTextToolbar.textAlign')" placement="top">
      <el-popover placement="bottom" trigger="hover">
        <template #default>
          <div class="fontOptionsList" :class="{ isDark }">
            <div
              class="fontOptionItem"
              v-for="item in alignListComputed"
              :key="item.value"
              :class="{ active: formatInfo.align === item.value }"
              @click="changeTextAlign(item.value)"
            >
              {{ item.name }}
            </div>
          </div>
        </template>
        <template #reference>
          <div class="btn">
            <span class="icon iconfont iconjuzhongduiqi"></span>
          </div>
        </template>
      </el-popover>
    </el-tooltip>

    <el-tooltip :content="t('richTextToolbar.removeFormat')" placement="top">
      <div class="btn" @click="removeFormat">
        <span class="icon iconfont iconqingchu"></span>
      </div>
    </el-tooltip>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onBeforeUnmount, defineProps } from 'vue'
import { storeToRefs } from 'pinia'
import { useI18n } from 'vue-i18n'
import { useMainStore } from '@/stores'
import { useEventBus } from '@/hooks'
import { fontFamilyList, fontSizeList, alignList } from '@/config'
import Color from './Color.vue'

// Props
const props = defineProps({
  mindMap: {
    type: Object
  }
})

// Composables
const { t, locale } = useI18n()
const store = useMainStore()
const { isDark } = storeToRefs(store)
const { $on, $off, $emit, $once } = useEventBus()

// Refs
const richTextToolbar = ref(null)

// Reactive data
const showRichTextToolbar = ref(false)
const style = reactive({
  left: 0,
  top: 0
})
const fontColor = ref('')
const fontBackgroundColor = ref('')
const formatInfo = reactive({})

// Computed
const fontFamilyListComputed = computed(() => {
  return fontFamilyList[locale.value] || fontFamilyList.zh
})

const alignListComputed = computed(() => {
  return alignList[locale.value] || alignList.zh
})

// Methods
const onRichTextSelectionChange = (hasRange, rect, formatInfoData) => {
  if (hasRange) {
    style.left = rect.left + rect.width / 2 + 'px'
    style.top = rect.top - 60 + 'px'
    Object.assign(formatInfo, { ...(formatInfoData || {}) })
  }
  showRichTextToolbar.value = hasRange
}

const toggleBold = () => {
  formatInfo.bold = !formatInfo.bold
  props.mindMap.richText.formatText({
    bold: formatInfo.bold
  })
}

const toggleItalic = () => {
  formatInfo.italic = !formatInfo.italic
  props.mindMap.richText.formatText({
    italic: formatInfo.italic
  })
}

const toggleUnderline = () => {
  formatInfo.underline = !formatInfo.underline
  props.mindMap.richText.formatText({
    underline: formatInfo.underline
  })
}

const toggleStrike = () => {
  formatInfo.strike = !formatInfo.strike
  props.mindMap.richText.formatText({
    strike: formatInfo.strike
  })
}

const changeFontFamily = (font) => {
  formatInfo.font = font
  props.mindMap.richText.formatText({
    font
  })
}

const changeFontSize = (size) => {
  formatInfo.size = size
  props.mindMap.richText.formatText({
    size: size + 'px'
  })
}

const changeFontColor = (color) => {
  formatInfo.color = color
  props.mindMap.richText.formatText({
    color
  })
}

const changeFontBackgroundColor = (background) => {
  formatInfo.background = background
  props.mindMap.richText.formatText({
    background
  })
}

const changeTextAlign = (align) => {
  formatInfo.align = align
  props.mindMap.richText.formatText({
    align
  })
}

const removeFormat = () => {
  props.mindMap.richText.removeFormat()
}

// Lifecycle hooks
onMounted(() => {
  $on('rich_text_selection_change', onRichTextSelectionChange)
  document.body.append(richTextToolbar.value)
})

onBeforeUnmount(() => {
  $off('rich_text_selection_change', onRichTextSelectionChange)
})
</script>

<style lang="less" scoped>
.richTextToolbar {
  position: fixed;
  z-index: 2000;
  height: 55px;
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: 8px;
  box-shadow: 0 2px 16px 0 rgba(0, 0, 0, 0.06);
  display: flex;
  align-items: center;
  transform: translateX(-50%);

  &.isDark {
    background: #363b3f;

    .btn {
      color: #fff;

      &:hover {
        background: hsla(0, 0%, 100%, 0.05);
      }
    }
  }

  .btn {
    width: 55px;
    height: 55px;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;

    &:hover {
      background-color: #eefbed;
    }

    &.active {
      color: #12bb37;
    }

    .icon {
      font-size: 20px;

      &.fontColor {
        font-size: 26px;
      }
    }
  }
}

.fontOptionsList {
  width: 150px;

  &.isDark {
    .fontOptionItem {
      color: #fff;

      &:hover {
        background-color: hsla(0, 0%, 100%, 0.05);
      }
    }
  }

  .fontOptionItem {
    height: 30px;
    width: 100%;
    display: flex;
    align-items: center;
    cursor: pointer;

    &:hover {
      background-color: #f7f7f7;
    }

    &.active {
      color: #12bb37;
    }
  }
}
</style>
